﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using BeanboxSoftware.BeanProxy;

namespace BeanProxyTest
{
  [TestClass]
  public class CallbackBehaviorTest
  {
    private CustomClass _proxy;
    private FuncConfig<int> _fooConfig;

    [TestInitialize]
    public void SetUp()
    {
      _proxy = ProxyManager.CreateProxy<CustomClass>();
      _fooConfig = ProxyManager.GetFunc<int>(_proxy.Foo);
    }

    [TestMethod]
    public void CallbackDefaultRepeatTest()
    {
      Assert.AreEqual(CallbackBehavior.Repeat, _fooConfig.Behavior);

      _fooConfig.Return = 4;

      for (int i = 0; i < 3; i++)
      {
        Assert.AreEqual(4, _proxy.Foo());
      }
    }

    [TestMethod]
    public void CallbackDefaultRepeatLoopTest()
    {
      _fooConfig.Callback = () => 1;
      _fooConfig.Callback += () => 2;
      _fooConfig.Callback += () => 3;

      for (int i = 0; i < 3; i++)
      {
        Assert.AreEqual(1, _proxy.Foo());
        Assert.AreEqual(2, _fooConfig.Invoke()); //doesn't matter which version you call
        Assert.AreEqual(3, _proxy.Foo());
      }
    }

    [TestMethod]
    public void CallbackRunOnceTest()
    {
      _fooConfig.Behavior = CallbackBehavior.RunOnce;

      _fooConfig.Callback = () => 1;
      _fooConfig.Callback += () => 2;

      Assert.AreEqual(1, _proxy.Foo());
      Assert.AreEqual(2, _proxy.Foo());
      TestUtils.AssertExceptionThrown<InvalidOperationException>(() => _proxy.Foo());
      TestUtils.AssertExceptionThrown<InvalidOperationException>(() => _proxy.Foo());
    }

    [TestMethod]
    public void CallbackRepeatLastTest()
    {
      _fooConfig.Behavior = CallbackBehavior.RepeatLast;

      _fooConfig.Callback = () => 1;
      _fooConfig.Callback += () => 2;

      Assert.AreEqual(1, _proxy.Foo());
      Assert.AreEqual(2, _proxy.Foo());

      Assert.AreEqual(2, _proxy.Foo());
      Assert.AreEqual(2, _proxy.Foo());
      Assert.AreEqual(2, _proxy.Foo());
    }

    [TestMethod]
    public void AssignClearTest()
    {
      _fooConfig.Callback += () => 1;
      _fooConfig.Callback += () => 2;

      _fooConfig.Callback = () => 3;

      Assert.AreEqual(3, _fooConfig.Invoke());
    }
  }

  public abstract class CustomClass
  {
    public abstract int Foo();
  }
}
